#include "App.h"




int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
				   PSTR cmdLine, int showCmd)
{
#if defined(DEBUG) | defined(_DEBUG)
	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

	PrimTopologyApp theApp(hInstance);
	
	theApp.initApp();

	return theApp.run();
}



void PrimTopologyApp::initApp()
{
	D3DApp::initApp();
	mPointList.init(md3dDevice, 1.0f);
	mLineStrip.init(md3dDevice, 1.0f);
	mTriangleStrip.init(md3dDevice, 1.0f);

	buildFX();
	buildVertexLayouts();
}

void PrimTopologyApp::onResize()
{
	D3DApp::onResize();
	float aspect = (float) mClientWidth / mClientHeight;

	D3DXMatrixPerspectiveFovLH(&mProj, 0.25f*PI, aspect, 1.0f, 1000.0f);
}

void PrimTopologyApp::updateScene(float dt)
{
	D3DApp::updateScene(dt);

	if (GetAsyncKeyState('A') & 0x8000)
		mTheta -= 2.0f * dt;
	if (GetAsyncKeyState('D') & 0x8000)
		mTheta += 2.0f * dt;
	if (GetAsyncKeyState('W') & 0x8000)
		mPhi -= 2.0f * dt;
	if (GetAsyncKeyState('S') & 0x8000)
		mPhi += 2.0f * dt;

	if (mPhi < 0.1f)	mPhi = 0.1f;
	if (mPhi > PI-0.1f)	mPhi = PI-0.1f;

	float y =  5.0f * cosf(mPhi);
	float xz = 5.0f * sinf(mPhi);
	float x =  xz * sinf(mTheta);
	float z = -xz * cosf(mTheta);

	D3DXVECTOR3	pos(x, y, z);
	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
	D3DXMatrixLookAtLH(&mView, &pos, &target, &up);
}

void PrimTopologyApp::drawScene()
{
	D3DApp::drawScene();
	
	// restore default states
	float blendFactors[] = {0.0f, 0.0f, 0.0f, 0.0f};
	md3dDevice->OMSetDepthStencilState(0, 0);
	md3dDevice->OMSetBlendState(0, blendFactors, 0xffffffff);
	md3dDevice->IASetInputLayout(mVertexLayout);
	md3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	// set constants
	mWVP = mView * mProj;
	mfxWVPVar->SetMatrix( (float*) &mWVP );

	D3D10_TECHNIQUE_DESC techDesc;
	mTech->GetDesc( &techDesc );
	for (UINT p = 0; p < techDesc.Passes; ++p) {
		mTech->GetPassByIndex( p )->Apply( 0 );
		//mPointList.draw();
		//mLineStrip.draw();
		mTriangleStrip.draw();
	}

	RECT rect = {5, 5, 0, 0};
	mFont->DrawText(0, mFrameStats.c_str(), -1, &rect, DT_NOCLIP, BLACK);

	mSwapChain->Present(0, 0);
}

void PrimTopologyApp::buildFX()
{
	DWORD shaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
#if defined(DEBUG) | defined(_DEBUG)
	shaderFlags |= D3D10_SHADER_DEBUG;
	shaderFlags |= D3D10_SHADER_SKIP_OPTIMIZATION;
#endif
	ID3D10Blob	*compilationErrors = 0;
	HRESULT hr = 0;
	hr = D3DX10CreateEffectFromFile(L"color.fx", 0, 0,
		"fx_4_0", shaderFlags, 0, md3dDevice, 0, 0, &mFX,
		&compilationErrors, 0);
	if ( FAILED(hr) ) {
		if ( compilationErrors ) {
			MessageBoxA(0,
				(char*) compilationErrors->GetBufferPointer(), 0, 0);
			ReleaseCOM(compilationErrors);
		}
		DXTrace(__FILE__, (DWORD)__LINE__, hr,
			L"D3DX10CreateEffectFromFile", true);
	}

	mTech = mFX->GetTechniqueByName("ColorTech");
	mfxWVPVar = mFX->GetVariableByName("gWVP")->AsMatrix();
}

void PrimTopologyApp::buildVertexLayouts()
{
	// create the vertex input layout
	D3D10_INPUT_ELEMENT_DESC vertexDesc[] = {
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
		D3D10_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12,
		D3D10_INPUT_PER_VERTEX_DATA, 0 }
	};

	D3D10_PASS_DESC passDesc;
	mTech->GetPassByIndex( 0 )->GetDesc(&passDesc);
	HR( md3dDevice->CreateInputLayout(vertexDesc, 2,
		passDesc.pIAInputSignature,
		passDesc.IAInputSignatureSize, &mVertexLayout) );
}
